#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include "Common.hpp"
#include "InetAddr.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include <memory>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <unistd.h>
using namespace LogModule;
using namespace SocketModule;
const static int SIZE = 64;
const static int defaultfd = -1;
class EpollServer {
public:
    EpollServer(int port) : _isrunning(false), _listensock(std::make_unique<TcpSocket>()), _epfd(defaultfd) {
        _listensock->BuildTcpSocketMethod(port);
        _epfd = epoll_create(256);
        if(_epfd < 0) {
            LOG(LogLevel::FATAL) << "epoll_create error";
            exit(EPOLL_CREATE_ERR);
        }
        LOG(LogLevel::INFO) << "epoll_create success, _epfd : " << _epfd;
        struct epoll_event ev;
        ev.events = EPOLLIN;
        ev.data.fd = _listensock->Fd();
        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, _listensock->Fd(), &ev);
        if(n < 0) {
            LOG(LogLevel::FATAL) << "epoll_ctl error";
            exit(EPOLL_CTL_ERR);
        }
    }
    void Start() {
        _isrunning = true;
        while (_isrunning) {
            int n = epoll_wait(_epfd, _revs, SIZE, -1);
            if(n == 0) {
                LOG(LogLevel::DEBUG) << "epoll_wait timeout";
            }else if(n < 0) {
                LOG(LogLevel::ERROR) << "epoll_wait error";
            }else {
                Dispatcher(n);
            }
        }
        _isrunning = false;
    }
    void Dispatcher(int n) {
        LOG(LogLevel::DEBUG) << "event ready";
        for(int i = 0; i < n; i++) {
            int sockfd = _revs[i].data.fd;
            uint32_t revent = _revs->events;
            if(revent & EPOLLIN) {
                if(sockfd == _listensock->Fd()) {
                    Accepter();
                }else {
                    Recver(sockfd);
                }
            }
        }
    }
    void Accepter() {
        InetAddr client;
        int sockfd = _listensock->Accept(&client);
        if(sockfd > 0) {
            LOG(LogLevel::INFO) << "获取到了一个新连接：sockfd :" << sockfd << ", client is " << client.StringAddr();
            struct epoll_event ev;
            ev.events = EPOLLIN;
            ev.data.fd = sockfd;
            int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &ev);
            if(n < 0) {
                LOG(LogLevel::WARNING) << "epoll_ctl error";
            }else {
                LOG(LogLevel::INFO) << "epoll_ctl success";
            }
        }
    }
    void Recver(int fd) {
        char buffer[1024];
        int n = recv(fd, buffer, sizeof(buffer) - 1, 0);
        if(n == 0) {
            LOG(LogLevel::INFO) << "client quit";
            int m = epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
            if(m > 0) {
                LOG(LogLevel::INFO) << "epoll_ctl delete sockfd success, sockfd : " << fd;
            }
            close(fd);
        }else if(n > 0) {
            buffer[n] = '\0';
            std::cout << "client say# " << buffer;
        }else {
            LOG(LogLevel::ERROR) << "recv error";
            int n = epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
            if(n > 0) {
                LOG(LogLevel::INFO) << "epoll_ctl delete sockfd success, sockfd : " << fd;
            }
            close(fd);
        }
    }   
    void Stop() {
        _isrunning = false;
    }
    ~EpollServer() {
        _listensock->Close();
        if(_epfd > 0) {
            close(_epfd);
        }
    }
private:
    bool _isrunning;
    struct epoll_event _revs[SIZE];
    int _epfd;
    std::unique_ptr<Socket> _listensock;
};